////////////////////////////////////////////////////////////////////////////////
/// @brief query parsing
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#ifndef TRIAGENS_DURHAM_VOC_BASE_QUERY_PARSE_H
#define TRIAGENS_DURHAM_VOC_BASE_QUERY_PARSE_H 1

#include <BasicsC/voc-errors.h>

#include "VocBase/query-base.h"
#include "VocBase/query-memory.h"
#include "QL/optimize.h"

#ifdef __cplusplus
extern "C" {
#endif

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
/// @brief Maximum length of an identifier in a query
////////////////////////////////////////////////////////////////////////////////

#define TRI_QUERY_ALIAS_MAX_LENGTH 64

// -----------------------------------------------------------------------------
// --SECTION--                                                          forwards
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief Forward declaration for parse function as generated by flex/bison
////////////////////////////////////////////////////////////////////////////////

int QLparse (TRI_query_template_t* const);
int QLlex_destroy (void *);
void QLset_extra (TRI_query_template_t* const, void*);
int QLlex_init (void**);
int QLget_lineno (void*);
int QLget_column (void*);

// -----------------------------------------------------------------------------
// --SECTION--                                                            parser
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief Parse the query contained in a query template
////////////////////////////////////////////////////////////////////////////////

bool TRI_ParseQueryTemplate (TRI_query_template_t* const);

// -----------------------------------------------------------------------------
// --SECTION--                                           parser helper functions
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief copies a string and keeps track of its memory location in a vector
///
/// This mimics TRI_DuplicateString (@ref TRI_DuplicateString) but also keeps
/// track of the strings memory location for later garbage collection.
////////////////////////////////////////////////////////////////////////////////

char* TRI_ParseQueryAllocString (TRI_query_template_t* const, const char*);

////////////////////////////////////////////////////////////////////////////////
/// @brief copies a string part and keeps track of its memory location in a vector
///
/// This mimics TRI_DuplicateString2 (@ref TRI_DuplicateString2) but also keeps
/// track of the strings memory location for later garbage collection.
////////////////////////////////////////////////////////////////////////////////

char* TRI_ParseQueryAllocString2 (TRI_query_template_t* const, 
                                  const char*, 
                                  const size_t);

////////////////////////////////////////////////////////////////////////////////
/// @brief keep track of an allocated string
///
/// Register a strings memory location for later garbage collection
////////////////////////////////////////////////////////////////////////////////

char* TRI_ParseQueryRegisterString (TRI_query_template_t* const, const char*);

////////////////////////////////////////////////////////////////////////////////
/// @brief free a string
///
/// Free memory that was allocated for a string
////////////////////////////////////////////////////////////////////////////////

void TRI_ParseQueryFreeString (char*);

////////////////////////////////////////////////////////////////////////////////
/// @brief create a new node for the ast
///
/// Create a new AST node of the given type (@ref TRI_query_node_type_e)
////////////////////////////////////////////////////////////////////////////////

TRI_query_node_t* TRI_ParseQueryCreateNode (TRI_query_template_t* const, 
                                            const TRI_query_node_type_e); 

////////////////////////////////////////////////////////////////////////////////
/// @brief open a new context layer for the parser
///
/// Layers are currently necessary to keep track of non-hierarchical lists
/// (arrays, objects) in the parser.
////////////////////////////////////////////////////////////////////////////////

void TRI_ParseQueryContextPush (TRI_query_template_t* const, TRI_query_node_t*);

////////////////////////////////////////////////////////////////////////////////
/// @brief close the current context layer of the parser and return it
////////////////////////////////////////////////////////////////////////////////

TRI_query_node_t* TRI_ParseQueryContextPop (TRI_query_template_t* const);

////////////////////////////////////////////////////////////////////////////////
/// @brief add an element to the current parsing context
////////////////////////////////////////////////////////////////////////////////

void TRI_ParseQueryContextAddElement (TRI_query_template_t* const, TRI_query_node_t*);

////////////////////////////////////////////////////////////////////////////////
/// @brief pop the current parse context from the stack into the rhs element
////////////////////////////////////////////////////////////////////////////////

void TRI_ParseQueryPopIntoRhs (TRI_query_node_t*, TRI_query_template_t* const);

// -----------------------------------------------------------------------------
// --SECTION--                                                        validation
// -----------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
/// @brief Validation function typedef to validate collection names
////////////////////////////////////////////////////////////////////////////////

typedef bool(*QL_parser_validate_func) (QL_ast_query_t*, const char*, const size_t);

////////////////////////////////////////////////////////////////////////////////
/// @brief Validate a collection name
///
/// Currently, a collection name must consist of the letters A-Z or a-z only
/// Its length must not exceed QL_QUERY_NAME_LEN chars.
////////////////////////////////////////////////////////////////////////////////

bool TRI_ParseQueryValidateCollectionName (const char*);

////////////////////////////////////////////////////////////////////////////////
/// @brief Validate a collection alias
///
/// Currently, a collection name must consist of the letters A-Z or a-z only
/// Its length must not exceed QL_QUERY_NAME_LEN chars.
////////////////////////////////////////////////////////////////////////////////

bool TRI_ParseQueryValidateCollectionAlias (const char*);

////////////////////////////////////////////////////////////////////////////////
/// @brief Validate the function names used in a query part
////////////////////////////////////////////////////////////////////////////////

bool TRI_ParseQueryValidateFunctionCalls (TRI_query_template_t* const,
                                          const TRI_query_node_t* const);

////////////////////////////////////////////////////////////////////////////////
/// @brief Validate the collections used in a query part
///
/// Currently validates if all used collection names in the query part are 
/// actually declared in the query's from clause.
////////////////////////////////////////////////////////////////////////////////

bool TRI_ParseQueryValidateCollections (TRI_query_template_t* const, 
                                        const TRI_query_node_t* const,
                                        QL_parser_validate_func,
                                        size_t*);

////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

#ifdef __cplusplus
}
#endif

#endif

// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

